package com.mini.test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class NumSummer {

	public static void main(String[] args) {
		// 数组规模
		int itemNum = 10000000;
		// 线程数目
		int threadNum = 18;

		// 初始化数组
		List<Integer> list = new ArrayList<Integer>(itemNum);
		for (int i = 1; i <= itemNum; i++) {
			list.add(i);
		}

		// 单线程运算
		long startTime = System.currentTimeMillis();
		long sum = 0;
		for (Integer item : list) {
			sum += item;
		}
		long usedTime = System.currentTimeMillis() - startTime;
		System.out
				.println("[单线程] Sum is : " + sum + " , time is : " + usedTime);

		// 多线程运算
		startTime = System.currentTimeMillis();
		int offset = itemNum / threadNum;
		int remain = itemNum % threadNum;
		List<Callable<Long>> calls = new ArrayList<Callable<Long>>(threadNum);
		int i = 0;
		for (; i < threadNum; i++) {
			calls.add(new SumCallable(list, i * offset, offset));
		}
		if (remain != 0) {
			calls.add(new SumCallable(list, i * offset, remain));
		}
		ExecutorService exeSvc = Executors.newFixedThreadPool(threadNum);
		try {
			List<Future<Long>> futuers = exeSvc.invokeAll(calls);
		
			sum = 0;
			for (Future<Long> futuer : futuers) {
				sum += futuer.get();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			exeSvc.shutdown();
		}
		usedTime = System.currentTimeMillis() - startTime;
		System.out
				.println("[多线程] Sum is : " + sum + " , time is : " + usedTime);
	}

	private static class SumCallable implements Callable<Long> {
		private List<Integer> items;
		private int start;
		private int offset;

		public SumCallable(List<Integer> items, int start, int offset) {
			this.items = items;
			this.start = start;
			this.offset = offset;
		}

		public Long call() throws Exception {
			long sum = 0;
			for (int i = start; i < start + offset; i++) {
				sum += items.get(i);
			}
			return sum;
		}
	}

}
